package com.ticket.system.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.util.MapUtils;
import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.google.common.collect.Maps;
import com.ticket.common.utils.DateUtils;
import com.ticket.system.domain.YanchuStatisticsOpera;
import com.ticket.system.mapper.YanchuStatisticsOperaMapper;
import com.ticket.system.service.IYanchuStatisticsOperaService;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;

/**
 * 【请填写功能名称】Service业务层处理
 * 
 * @author ruoyi
 * @date 2024-03-14
 */
@Service
public class YanchuStatisticsOperaServiceImpl implements IYanchuStatisticsOperaService 
{
    @Autowired
    private YanchuStatisticsOperaMapper yanchuStatisticsOperaMapper;

    private static final Logger logger = LoggerFactory.getLogger(YanchuStatisticsOperaServiceImpl.class);

    @Value("${tempUrl}")
    private String tempUrl;

    /**
     * 查询【请填写功能名称】
     * 
     * @param id 【请填写功能名称】主键
     * @return 【请填写功能名称】
     */
    @Override
    public YanchuStatisticsOpera selectYanchuStatisticsOperaById(Long id)
    {
        return yanchuStatisticsOperaMapper.selectYanchuStatisticsOperaById(id);
    }

    /**
     * 查询【请填写功能名称】列表
     * 
     * @param yanchuStatisticsOpera 【请填写功能名称】
     * @return 【请填写功能名称】
     */
    @Override
    public List<YanchuStatisticsOpera> selectYanchuStatisticsOperaList(YanchuStatisticsOpera yanchuStatisticsOpera)
    {
        return yanchuStatisticsOperaMapper.selectYanchuStatisticsOperaList(yanchuStatisticsOpera);
    }

    /**
     * 新增【请填写功能名称】
     * 
     * @param yanchuStatisticsOpera 【请填写功能名称】
     * @return 结果
     */
    @Override
    public int insertYanchuStatisticsOpera(YanchuStatisticsOpera yanchuStatisticsOpera)
    {
        yanchuStatisticsOpera.setCreateTime(DateUtils.getNowDate());
        return yanchuStatisticsOperaMapper.insertYanchuStatisticsOpera(yanchuStatisticsOpera);
    }

    /**
     * 修改【请填写功能名称】
     * 
     * @param yanchuStatisticsOpera 【请填写功能名称】
     * @return 结果
     */
    @Override
    public int updateYanchuStatisticsOpera(YanchuStatisticsOpera yanchuStatisticsOpera)
    {
        return yanchuStatisticsOperaMapper.updateYanchuStatisticsOpera(yanchuStatisticsOpera);
    }

    /**
     * 批量删除【请填写功能名称】
     * 
     * @param ids 需要删除的【请填写功能名称】主键
     * @return 结果
     */
    @Override
    public int deleteYanchuStatisticsOperaByIds(Long[] ids)
    {
        return yanchuStatisticsOperaMapper.deleteYanchuStatisticsOperaByIds(ids);
    }

    /**
     * 删除【请填写功能名称】信息
     * 
     * @param id 【请填写功能名称】主键
     * @return 结果
     */
    @Override
    public int deleteYanchuStatisticsOperaById(Long id)
    {
        return yanchuStatisticsOperaMapper.deleteYanchuStatisticsOperaById(id);
    }

    /**
     * 场次统计
     * @return
     */
    @Override
    public List<Map<String,Object>> staticsSessionByOpera()
    {
        return yanchuStatisticsOperaMapper.staticsSessionByOpera();
    }

    /**
     * 销售额统计
     * @return
     */
    @Override
    public List<Map<String, Object>> staticsOrderByOpera()
    {
        List<Map<String, Object>> list = yanchuStatisticsOperaMapper.staticsAllOrderByOpera();
//        List<Map<String, Object>> listToday = yanchuStatisticsOperaMapper.staticsOrderByOperaToday();
//        Map<String,BigDecimal> todayMap = Maps.newHashMap();
//        BigDecimal sellsMoney = null;
//        String hallName = null;
//        if(CollectionUtils.isNotEmpty(listToday)){
//            for(Map<String, Object> map:listToday){
//                todayMap.put((String)map.get("content"),(BigDecimal)map.get("value"));
//            }
//            for(Map<String,Object> map:list){
//                hallName = (String)map.get("content");
//                sellsMoney = (BigDecimal) map.get("value");
//                if(todayMap.get(hallName) == null){
//                    continue;
//                }
//                sellsMoney = sellsMoney.add(todayMap.get(hallName));
//                map.put("value",sellsMoney);
//            }
//        }

        return list;
    }
    /**
     * 客单价统计
     * @return
     */
    @Override
    public List<Map<String, Object>> staticsPerOrderByOpera(){
        List<Map<String, Object>> list = yanchuStatisticsOperaMapper.staticsAllOrderByOpera();//总销售
        List<Map<String, Object>> listTicket = yanchuStatisticsOperaMapper.staticsAllByOperaTicket();//总票数
        Map<String,Long> ticketMap = Maps.newHashMap();
        BigDecimal sellsMoney = null;
        Long tickets = null;
        String hallName = null;
        if(CollectionUtils.isNotEmpty(listTicket)){
            for(Map<String, Object> map:listTicket){
                ticketMap.put((String)map.get("content"),(Long)map.get("sellsTickets"));
            }
        }
        for(Map<String,Object> map:list){
            hallName = (String)map.get("content");
            sellsMoney = (BigDecimal) map.get("value");
            tickets = ticketMap.get(hallName);
            if(null != tickets){
                map.put("value",sellsMoney.divide(BigDecimal.valueOf(tickets),2,BigDecimal.ROUND_HALF_UP));
            }

            map.remove("sellsTickets");
        }
        Collections.sort(list,new Comparator<Map>() {
            @Override
            public int compare(Map o1, Map o2) {
                return ((BigDecimal)o2.get("value")).compareTo((BigDecimal)o1.get("value"));
            }
        });
        if(list.size() < 5){
            return list;
        }else{
            return list.subList(0,5);
        }
    }
    @Override
    public Map<String, Object> staticsByOperaGlobla(String startTime,String endTime,Long operaId,Long hallId){
        //基础情况
        List<Map<String, Object>> listBasic = yanchuStatisticsOperaMapper.listBusinessByHall(operaId,hallId);
        // 票房规划情况 上架场次 上架演出
        List<Map<String, Object>> listSession = yanchuStatisticsOperaMapper.listBusinessBySessionData(startTime,endTime,operaId,hallId);
        logger.info("listSession:{}",listSession);
        //销售收入
        List<Map<String, Object>> listSells = yanchuStatisticsOperaMapper.listBusinessBySells(startTime,endTime,operaId,hallId);
        //小程序购票人数
        List<Map<String, Object>> listProgUser = yanchuStatisticsOperaMapper.listBusinessBySellsProg(startTime,endTime,operaId,hallId);
        listSells.get(0).putAll(listProgUser.get(0));
        logger.info("listSells:{}",listSells);
        //平均规划票价：规划总金额÷规划票数
        BigDecimal totalMoneyExpect = (BigDecimal)listSession.get(0).get("totalMoneyExpect");
        BigDecimal seatNumsExpect = (BigDecimal)listSession.get(0).get("seatNumsExpect");
        if(null!=seatNumsExpect && seatNumsExpect.compareTo(BigDecimal.ZERO)>0){
            listSession.get(0).put("averExpect",totalMoneyExpect.divide(seatNumsExpect,2,BigDecimal.ROUND_HALF_UP));
        }else{
            listSession.get(0).put("averExpect",0);
        }

        //总售出票数
        BigDecimal sallNums = (BigDecimal)listSells.get(0).get("sallNums");

        //平均销售票价：总票务销售收入÷总售出票数
        BigDecimal selledMoney = (BigDecimal)listSells.get(0).get("selledMoney");
        BigDecimal totalRefundCount = (BigDecimal)listSells.get(0).get("totalRefundCount");
        if(null != sallNums && sallNums.compareTo(BigDecimal.ZERO)>0){
            listSells.get(0).put("averSellPriceRatio",selledMoney.divide(sallNums,2,BigDecimal.ROUND_HALF_UP));
            //退票率：总退票数÷总售出票数（含售出又退票的票数）
            listSells.get(0).put("refundRatio",totalRefundCount.divide(sallNums.add(totalRefundCount),4,BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100)).setScale(2,BigDecimal.ROUND_HALF_UP)+"%");
        }else{
            listSells.get(0).put("averSellPriceRatio","0");
            listSells.get(0).put("refundRatio","0%");
        }

        //人均消费金额：小程序售票总金额÷小程序购票人数
        BigDecimal totalMoneyProg = (BigDecimal)listSells.get(0).get("totalMoneyByProg");
        Long countProgUsers = (Long)listSells.get(0).get("countProgUsers");
        if(countProgUsers>0){
            listSells.get(0).put("averConsumePrice",totalMoneyProg.divide(BigDecimal.valueOf(countProgUsers),2,BigDecimal.ROUND_HALF_UP));
        }else{
            listSells.get(0).put("averConsumePrice",0);
        }

        //总体上座率：总出票数（含普通、团购、其他、赠票、工作票）÷规划票数
        if(seatNumsExpect.compareTo(BigDecimal.ZERO)>0){
            //总体上座率：【总出票数（含普通票、团购票、赠票、工作票、其他票）÷总规划票数】×100%
            BigDecimal seatPercent = sallNums.divide(seatNumsExpect,4,BigDecimal.ROUND_HALF_UP);
            listSells.get(0).put("seatPercent",seatPercent.multiply(BigDecimal.valueOf(100)).setScale(2,BigDecimal.ROUND_HALF_UP)+"%");
            //平均售出率：（总售出票数÷规划票数）*100%
            listSells.get(0).put("averSellRatio",sallNums.divide(seatNumsExpect,4,BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100)).setScale(2,BigDecimal.ROUND_HALF_UP)+"%");
        }else{
            listSells.get(0).put("seatPercent","0%");
            listSells.get(0).put("averSellRatio","0%");
        }
        listBasic.get(0).putAll(listSession.get(0));
        listBasic.get(0).putAll(listSells.get(0));
        return listBasic.get(0);
    }

    @Override
    public List<Map<String, Object>> ticketFromRanking(String startTime,String endTime,String orderBy,String sort,Long operaId,Long hallId){
        //门票类型分布
        List<Map<String, Object>> ticketFromRanking = yanchuStatisticsOperaMapper.listBusinessByTicketFrom(startTime,endTime,orderBy,sort,
                operaId,hallId);
        if(CollectionUtils.isNotEmpty(ticketFromRanking)){
            Long totalTicket = 0l;
            for(Map<String, Object> map:ticketFromRanking){
                totalTicket=totalTicket+(Long)map.get("ticketNums");
            }
            Long ticketCount = null;
            BigDecimal percent = null;
            for(int i=0;i<ticketFromRanking.size();i++){
                ticketFromRanking.get(i).put("index",(i+1)+"");
                ticketCount = (Long)ticketFromRanking.get(i).get("ticketNums");
                percent = BigDecimal.valueOf(ticketCount).divide(BigDecimal.valueOf(totalTicket),4,BigDecimal.ROUND_HALF_UP);
                ticketFromRanking.get(i).put("ratio",percent.multiply(BigDecimal.valueOf(100)).setScale(2,BigDecimal.ROUND_HALF_UP)+"%");
            }
        }
        return ticketFromRanking;
    }

    @Override
    public List<Map<String, Object>> performTypeRanking(String startTime,String endTime,String orderBy,String sort,Long operaId,Long hallId){
        // 演出类型分析
        List<Map<String, Object>> performTypeRanking = yanchuStatisticsOperaMapper.listBusinessByPerform(startTime,endTime,orderBy,sort,
                operaId,hallId);
        if(CollectionUtils.isNotEmpty(performTypeRanking)){
            Long totalTicket = 0l;
            for(Map<String, Object> map:performTypeRanking){
                totalTicket=totalTicket+(Long)map.get("ticketNums");
            }
            Long ticketCount = null;
            BigDecimal percent = null;
            for(int i=0;i<performTypeRanking.size();i++){
                performTypeRanking.get(i).put("index",(i+1)+"");
                ticketCount = (Long)performTypeRanking.get(i).get("ticketNums");
                percent = BigDecimal.valueOf(ticketCount).divide(BigDecimal.valueOf(totalTicket),4,BigDecimal.ROUND_HALF_UP);
                performTypeRanking.get(i).put("ratio",percent.multiply(BigDecimal.valueOf(100)).setScale(2,BigDecimal.ROUND_HALF_UP)+"%");
            }
        }
        return performTypeRanking;
    }

    @Override
    public List<Map<String, Object>> performSellsRanking(String startTime,String endTime,String orderBy,String sort,Long operaId,Long hallId){
        //演出销售排名
        List<Map<String, Object>> sellsRanking = yanchuStatisticsOperaMapper.listBusinessByPerformSells(startTime,endTime,orderBy,sort,
                operaId,hallId);
        if(CollectionUtils.isNotEmpty(sellsRanking)){
            Long totalTicket = 0l;
            for(Map<String, Object> map:sellsRanking){
                totalTicket=totalTicket+(Long)map.get("ticketNums");
            }
            Long ticketCount = null;
            BigDecimal percent = null;
            for(int i=0;i<sellsRanking.size();i++){
                sellsRanking.get(i).put("index",(i+1)+"");
                ticketCount = (Long)sellsRanking.get(i).get("ticketNums");
                percent = BigDecimal.valueOf(ticketCount).divide(BigDecimal.valueOf(totalTicket),4,BigDecimal.ROUND_HALF_UP);
                sellsRanking.get(i).put("ratio",percent.multiply(BigDecimal.valueOf(100)).setScale(2,BigDecimal.ROUND_HALF_UP)+"%");

            }
        }
        return sellsRanking;
    }

    @Override
    public List<Map<String, Object>> sessionSellsRanking(String startTime,String endTime,String orderBy,String sort,Long operaId,Long hallId){
        //场次销售排名
        List<Map<String, Object>> sessionRanking = yanchuStatisticsOperaMapper.listBusinessBySessionSells(startTime,endTime,orderBy,sort,
                operaId,hallId);
        if(CollectionUtils.isNotEmpty(sessionRanking)){
            for(int i=0;i<sessionRanking.size();i++){
                sessionRanking.get(i).put("index",(i+1)+"");
            }
        }
        return sessionRanking;
    }

    @Override
    public void exportStaticsByOperaGlobla(String startTime,String endTime,Long operaId,Long hallId,HttpServletResponse response) {
        Map<String,Object> mapCollect = staticsByOperaGlobla(startTime,endTime,operaId,hallId);
        List<Map<String, Object>> ticketFromRanking = ticketFromRanking(startTime,endTime,null,null,operaId,hallId);
        List<Map<String, Object>> performTypeRanking = performTypeRanking(startTime,endTime,null,null,operaId,hallId);
        List<Map<String, Object>> performSellsRanking = performSellsRanking(startTime,endTime,null,null,operaId,hallId);
        List<Map<String, Object>> sessionSellsRanking = sessionSellsRanking(startTime,endTime,null,null,operaId,hallId);

        // 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
        String templateFileName = tempUrl + "operaBusinessExportTemp.xlsx";
        String fileName = "operaBusinessExport"+System.currentTimeMillis()+".xlsx";
//        String fileName = "C:/Users/lovepig/Desktop/" + "导出订单列表" + System.currentTimeMillis() + ".xlsx";
        try {
            //替换成自己的数据
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName);
            ExcelWriterBuilder write = EasyExcel.write(response.getOutputStream());

            //只有一个直接写 >1的合并 分开写入
            try (ExcelWriter excelWriter = write.withTemplate(templateFileName).build()){
                WriteSheet writeSheet = EasyExcel.writerSheet(0).build();
                excelWriter.fill(mapCollect, writeSheet);

                WriteSheet writeSheet1 = EasyExcel.writerSheet(1).build();
                FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
                excelWriter.fill(ticketFromRanking, fillConfig, writeSheet1);
                Map<String, Object> map = MapUtils.newHashMap();
                if(null != mapCollect.get("operaName")){
                    map.put("operaName", mapCollect.get("operaName"));
                }else{
                    map.put("operaName", "");
                }

                excelWriter.fill(map, writeSheet1);

                WriteSheet writeSheet2 = EasyExcel.writerSheet(2).build();
                excelWriter.fill(performTypeRanking, fillConfig, writeSheet2);
                excelWriter.fill(map, writeSheet2);
                WriteSheet writeSheet3 = EasyExcel.writerSheet(3).build();
                excelWriter.fill(performSellsRanking, fillConfig, writeSheet3);
                excelWriter.fill(map, writeSheet3);
                WriteSheet writeSheet4 = EasyExcel.writerSheet(4).build();
                excelWriter.fill(sessionSellsRanking, fillConfig, writeSheet4);
                excelWriter.fill(map, writeSheet4);
            }
        } catch (Exception e) {
            logger.error("exportPerformStatistics",e);
        }
    }
}
